Shader "URP-YoFi/Environment/Environment-Universal" 
{
	Properties
	{
		_MainColor("MainColor", Color) = (1,1,1,1)
		_MainTex ("Albedo", 2D) = "white" {}
        _RMATex ("RMA", 2D) = "white" {}
		_Metallic ("Metallic", Range(0,1)) = 1
        _Roughness ("Roughness", Range(0,1)) = 1
        [Normal]_NormalTex ("Normal", 2D) = "bump"{}
        _NormalScale("Normal Scale", Range(0,3)) = 1.0
        _AO("AO", Range(0,3)) = 1.0
		_ShadowColor("Shadow Color", Color) = (0.4,0.4,0.4,1)

		_FogStart("_Fog Start", Range(0,1000)) = 100
        _FogEnd("_Fog End", Range(0,1000)) = 200

        _BakedLightIntensity("Baked Light Intensity", Range(0,10)) = 1.0
		
	}

	SubShader 
	{
		Tags
		{
			"RenderType" = "Opaque"
            "Queue" = "Geometry"
		}
		
		HLSLINCLUDE
		
		#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
		#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
		#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
		
		TEXTURE2D(_MainTex);
		SAMPLER(sampler_MainTex);
		TEXTURE2D(_RMATex);
		SAMPLER(sampler_RMATex);
        TEXTURE2D (_NormalTex);
        SAMPLER(sampler_NormalTex);

		CBUFFER_START(UnityPerMaterial)
		float4 _NormalTex_ST;
        float _BakedLightIntensity;
        float _NormalScale;
		float _Metallic;
		float _Roughness;
		float _AO;
		float4 _MainColor;
		float4 _ShadowColor;

		float _FogStart;
		float _FogEnd;
		CBUFFER_END
		        
		ENDHLSL

		Pass
		{
			Tags{ "LightMode" = "UniversalForward" }
			Cull Off
			HLSLPROGRAM
			
			#pragma vertex vert
			#pragma fragment frag
			
			#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
			#pragma multi_compile _ _SHADOWS_SOFT
			//#pragma multi_compile _MAIN_LIGHT_SHADOWS_CASCADE
			#pragma multi_compile _ LIGHTMAP_ON
			//#pragma multi_compile _ FOG_LINEAR
			// #pragma multi_compile_fog
			//#pragma multi_compile _ LIGHTMAP_SHADOW_MIXING
            //#pragma multi_compile _ SHADOWS_SHADOWMASK
			//#pragma multi_compile _ CALCULATE_BAKED_SHADOWS
			

			void Unity_Remap_float(float In, float2 InMinMax, float2 OutMinMax, out float Out)
			{
			    Out = OutMinMax.x + (In - InMinMax.x) * (OutMinMax.y - OutMinMax.x) / (InMinMax.y - InMinMax.x);
			}
            //正态分布函数D
            float Distribution(float roughness2 , float nh)
            {
                float lerpSquareRoughness = pow(lerp(0.002, 1, roughness2), 2);
                float D = lerpSquareRoughness / (pow((pow(nh, 2) * (lerpSquareRoughness - 1) + 1), 2) * PI);
                return D;
            }

            //几何遮蔽G
            float Geometry(float roughness2 , float nl , float nv)
            {
                float kInDirectLight = pow(roughness2 + 1, 2) / 8;
                float kInIBL = pow(roughness2, 2) / 8;
                float GLeft = nl / lerp(nl, 1, kInDirectLight);
                float GRight = nv / lerp(nv, 1, kInDirectLight);
                float G = GLeft * GRight;
                return G;
            }

            //菲尼尔Fresnel
            float3 FresnelEquation(float3 F0 , float vh)
            {
                float3 F = F0 + (1 - F0) * exp2((-5.55473 * vh - 6.98316) * vh);
                return F;
            }

            //立方体贴图的Mip等级计算
            float CubeMapMip(float _Roughness)
            {
                //基于粗糙度计算CubeMap的Mip等级
                float mip_roughness = _Roughness * (1.7 - 0.7 * _Roughness);
                float mip = mip_roughness * UNITY_SPECCUBE_LOD_STEPS; 
                return mip;
            }

            //间接光的菲涅尔系数
            float3 fresnelSchlickRoughness(float cosTheta, float3 F0, float roughness2)
            {
                return F0 + (max(float3(1 ,1, 1) * (1 - roughness2), F0) - F0) * pow(1.0 - cosTheta, 5.0);
            }

			

			struct Attributes
			{
				float4 positionOS : POSITION;
				float3 normalOS     : NORMAL;
				float2 uv : TEXCOORD0;
				float2 uv2 : TEXCOORD1;
                float4 tangentOS : TANGENT;

			};

			struct Varyings
			{
				float4 positionHCS : SV_POSITION;
				float2 uv : TEXCOORD0;
				float2 uv2 : TEXCOORD1;
				float3 positionWS : TEXCOORD2;
				float3 normalWS  : TEXCOORD3;
                float3 tangentWS :TEXCOORD4;
                float3 BtangentWS : TEXCOORD5;

                float4 screenPos : TEXCOORD6;
				float fogFactor : TEXCOORD7;

				DECLARE_LIGHTMAP_OR_SH(lightmapUV, vertexSH,8);

			};

			Varyings vert (Attributes IN)
			{
				Varyings OUT;
				OUT.uv = IN.uv;
				OUT.uv2 = IN.uv2;
				OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz);
				OUT.positionWS = TransformObjectToWorld(IN.positionOS.xyz);
                OUT.normalWS = TransformObjectToWorldNormal(IN.normalOS).xyz;
                OUT.tangentWS = TransformObjectToWorldDir(IN.tangentOS.xyz);
                OUT.BtangentWS = cross(OUT.normalWS.xyz,OUT.tangentWS.xyz) * IN.tangentOS.w * unity_WorldTransformParams.w;

				OUT.screenPos = ComputeScreenPos(OUT.positionHCS);
				

				OUT.fogFactor = ComputeFogFactor(OUT.positionHCS.z);

                OUTPUT_LIGHTMAP_UV(IN.uv2, unity_LightmapST, OUT.lightmapUV);
                OUTPUT_SH(OUT.normalWS, OUT.vertexSH);
				return OUT;
			}

			half4 frag (Varyings IN) : SV_Target
			{



				//准备数据
                float4 screenPos = IN.screenPos;
                float3 normalWS = normalize(IN.normalWS);
                float3 tangentWS = normalize(IN.tangentWS);
                float3 BtangentWS = normalize(IN.BtangentWS);
				float3 positionWS = IN.positionWS;

                half4 NormalTex = SAMPLE_TEXTURE2D(_NormalTex ,sampler_NormalTex,IN.uv * _NormalTex_ST.xy + _NormalTex_ST.zw);   //法线贴图
                float3x3 TBN = {tangentWS,BtangentWS,normalWS};          //世界空间法线方向
                float3 normalTS = UnpackNormalScale(NormalTex,_NormalScale);               //控制法线强度
                normalTS.z = pow((1 - pow(normalTS.x,2) - pow(normalTS.y,2)),0.5);         //规范化法线
                normalWS = mul(normalTS,TBN);   //顶点法线，和法线贴图融合 == 世界空间的法线信息

                //物体世界坐标放入阴影计算
                float4 SHADOW_COORDS = TransformWorldToShadowCoord(IN.positionWS);
                //输出灯光数据
				half4 shadowMask = SAMPLE_SHADOWMASK(IN.lightmapUV);
				Light lightData = GetMainLight(SHADOW_COORDS, IN.positionWS, shadowMask);
				float3 lightDir = normalize(lightData.direction); 
                float3 lightColor = lightData.color;
                float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - IN.positionWS);
                float3 halfVector = normalize(lightDir + viewDir);      //半角向量

                half4 MainTex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, IN.uv);   
                half3 Albedo = MainTex.rgb * _MainColor.rgb;    //颜色
				half alpha = MainTex.a;
				half3 shadow = lerp( _ShadowColor.rgb,1, lightData.shadowAttenuation);
				half3 bakedGI = SAMPLE_GI(IN.lightmapUV, IN.vertexSH, normalWS) * _BakedLightIntensity;
				

				clip(alpha-0.3);
                    
				
                half3  finalResult =  Albedo * bakedGI;
				
				finalResult = MixFog(finalResult.rgb, IN.fogFactor);
				

				return half4(finalResult.rgb,1.0);
			}
			ENDHLSL 
		}
		Pass
        {
            Name "DepthOnly"
            Tags{"LightMode" = "DepthOnly"}

            ZWrite On
            ColorMask r
            Cull Back

            HLSLPROGRAM
            #pragma only_renderers gles gles3 glcore d3d11
            #pragma target 2.0
            #pragma vertex DepthOnlyVertex
            #pragma fragment DepthOnlyFragment
            // Material Keywords
            //#pragma shader_feature_local_fragment _ALPHATEST_ON
            //#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
            // GPU Instancing
            // #pragma multi_compile_instancing
            //#pragma shader_feature_local _ _ALPHATEST

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

            struct Attributes
            {
                float4 position     : POSITION;
                float2 texcoord     : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct Varyings
            {
                float4 positionCS   : SV_POSITION;
                float2 uv           : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
                UNITY_VERTEX_OUTPUT_STEREO
            };

            Varyings DepthOnlyVertex(Attributes input)
            {
                Varyings output = (Varyings)0;
                UNITY_SETUP_INSTANCE_ID(input);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
                //output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap);
                output.uv = input.texcoord;

                output.positionCS = TransformObjectToHClip(input.position.xyz);
                return output;
            }

            half4 DepthOnlyFragment(Varyings input) : SV_TARGET
            {
                UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
                // Alpha(SampleAlbedoAlpha(input.uv, TEXTURE2D_ARGS(_BaseMap, sampler_BaseMap)).a, _BaseColor, _Cutoff);
            // #if defined(_ALPHATEST)
            //     float transTex = SAMPLE_TEXTURE2D(_TransTex, sampler_TransTex, input.uv).r - _Transparent;
            //     clip(transTex);
            // #endif

                return half4(0,0,0,1);
            }
            ENDHLSL
        }

        Pass
        {
            Name "DepthNormals"
            Tags{"LightMode" = "DepthNormals"}

            ZWrite On
            Cull Back

            HLSLPROGRAM
            #pragma only_renderers gles gles3 glcore d3d11
            #pragma target 2.0
            #pragma vertex DepthNormalsVertex
            #pragma fragment DepthNormalsFragment
            // Material Keywords
            //#pragma shader_feature_local _NORMALMAP
            //#pragma shader_feature_local _PARALLAXMAP
            //#pragma shader_feature_local _ _DETAIL_MULX2 _DETAIL_SCALED
            //#pragma shader_feature_local_fragment _ALPHATEST_ON
            //#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
            // GPU Instancing
            // #pragma multi_compile_instancing

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            // #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
            // #include "Packages/com.unity.render-pipelines.universal/Shaders/LitDepthNormalsPass.hlsl"

            struct Attributes
            {
                float4 position     : POSITION;
                half3 normalOS      : NORMAL;
                // float2 texcoord     : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct Varyings
            {
                float4 positionCS   : SV_POSITION;
                float3 positionWS   : TEXCOORD1;
                half3  normalWS     : TEXCOORD2;
                // float2 uv           : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
                UNITY_VERTEX_OUTPUT_STEREO
            };

            Varyings DepthNormalsVertex(Attributes input)
            {
                Varyings output = (Varyings)0;
                UNITY_SETUP_INSTANCE_ID(input);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
                // output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap);
                output.positionCS = TransformObjectToHClip(input.position.xyz);
                output.normalWS = TransformObjectToWorldNormal(input.normalOS);
                return output;
            }

            half4 DepthNormalsFragment(Varyings input) : SV_TARGET
            {
                UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
                // Alpha(SampleAlbedoAlpha(input.uv, TEXTURE2D_ARGS(_BaseMap, sampler_BaseMap)).a, _BaseColor, _Cutoff);
                return half4(input.normalWS, 1);
            }
            ENDHLSL
        }

        Pass
        {
            Name "Meta"
            Tags{"LightMode" = "Meta"}

            Cull Off

            HLSLPROGRAM
            #pragma exclude_renderers gles gles3 glcore
            #pragma target 4.5

            #pragma vertex UniversalVertexMeta
            #pragma fragment UniversalFragmentMetaLit

            //#pragma shader_feature EDITOR_VISUALIZATION
            // #pragma shader_feature_local_fragment _SPECULAR_SETUP
            // #pragma shader_feature_local_fragment _EMISSION
            // #pragma shader_feature_local_fragment _METALLICSPECGLOSSMAP
            //#pragma shader_feature_local_fragment _ALPHATEST_ON
            //#pragma shader_feature_local_fragment _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
            //#pragma shader_feature_local _ _DETAIL_MULX2 _DETAIL_SCALED

            // #pragma shader_feature_local_fragment _SPECGLOSSMAP
            
			//#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
            
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/MetaInput.hlsl"
            

			struct Attributes
			{
			    float4 positionOS   : POSITION;
			    float3 normalOS     : NORMAL;
			    float2 uv0          : TEXCOORD0;
			    float2 uv1          : TEXCOORD1;
			    float2 uv2          : TEXCOORD2;
			    UNITY_VERTEX_INPUT_INSTANCE_ID
			};

			struct Varyings
			{
			    float4 positionCS   : SV_POSITION;
			    float2 uv           : TEXCOORD0;
			#ifdef EDITOR_VISUALIZATION
			    float2 VizUV        : TEXCOORD1;
			    float4 LightCoord   : TEXCOORD2;
			#endif
			};

			Varyings UniversalVertexMeta(Attributes input)
			{
			    Varyings output = (Varyings)0;
			    output.positionCS = UnityMetaVertexPosition(input.positionOS.xyz, input.uv1, input.uv2);
			    //output.uv = TRANSFORM_TEX(input.uv0, _BaseMap);
			    output.uv = input.uv0;
			#ifdef EDITOR_VISUALIZATION
			    UnityEditorVizData(input.positionOS.xyz, input.uv0, input.uv1, input.uv2, output.VizUV, output.LightCoord);
			#endif
			    return output;
			}

			half4 UniversalFragmentMeta(Varyings fragIn, MetaInput metaInput)
			{
			#ifdef EDITOR_VISUALIZATION
			    metaInput.VizUV = fragIn.VizUV;
			    metaInput.LightCoord = fragIn.LightCoord;
			#endif

			    return UnityMetaFragment(metaInput);
			}
            
            half4 UniversalFragmentMetaLit(Varyings input) : SV_Target
            {

            	half4 mainTex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv);    //颜色
				

                MetaInput metaInput;
                metaInput.Albedo = mainTex.rgb;
                metaInput.Emission = mainTex.rgb*mainTex.a;
                return UniversalFragmentMeta(input, metaInput);
            }
            
            
            ENDHLSL
        }


		Pass 
        {
            Name "ShadowCaster"
            Tags{ "LightMode" = "ShadowCaster" }
            Cull Back

            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag


            struct a2v {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float3 normal : NORMAL;
            };
            struct v2f {
                float4 vertex : SV_POSITION;
                float2 uv : TEXCOORD0;
            };

            v2f vert(a2v v)
            {
                v2f o = (v2f)0;
                float3 worldPos = TransformObjectToWorld(v.vertex.xyz);
                half3 normalWS = TransformObjectToWorldNormal(v.normal);
                Light mainLight =  GetMainLight();//获取主光源

                worldPos = ApplyShadowBias(worldPos, normalWS, mainLight.direction);
                o.vertex = TransformWorldToHClip(worldPos);
                o.uv = v.uv;
                return o;
            }
            real4 frag(v2f i) : SV_Target
            {
//#if _ALPHATEST_ON
                half4 MainTex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);   
                clip(MainTex.a - 0.3);
//#endif
                return 0;
            }
            ENDHLSL
        }
	}
}